﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

class Laser:Weapon
{
    public float        m_IsBilibili = 0;
    public float        m_Width =0.4f;
    protected float     m_Attenuation = 1;
    protected float     m_AttenuationCount = 1;
    protected float     m_EnergyConsumption = 3;
    protected LineRenderer m_Laser;
    protected string m_BoomEndEffect = "Perfabs/Effect/LaserBoomEnd";

    ParticleSystem m_LaserBoomEndObj;

    AudioSource m_LaserDuration;

    protected Vector4   m_StartColor = new Vector4(1, 1, 0, 1);
    protected Vector4   m_EndColor = new Vector4(1, 1, 0, 1);

    bool IsDamage = true;
    public Laser()
    {
        Damage = 10;
        m_ShotErrorValueBase = 0;
        m_ShotErrorValueMax = 1;
        m_ShotErrorValueIncrement = 0.5f;
    }
    public override void Init(Ship ship, WeaponSlot slot)
    {
        base.Init(ship, slot);
        m_Attenuation = ShutVelocity;
        var laser = new GameObject();
        laser.name = "Laser";
        m_Laser = laser.AddComponent<LineRenderer>();
        Vector3[] positions = new Vector3[2];
        m_Laser.SetPositions(positions);
        m_Laser.numCapVertices = 4;
        m_Laser.startWidth = m_Width;
        m_Laser.endWidth = m_Width;
        m_Laser.gameObject.SetActive(false);
        m_Laser.startColor = m_StartColor;
        m_Laser.endColor = m_EndColor;
        m_Laser.useWorldSpace = false;
        m_Laser.material = Resources.Load<Material>("Materials/Effects/Laser");
        m_Laser.material.color = new Vector4(1,1,1,1);
        m_Laser.sortingLayerName = "Item";
        m_Laser.transform.SetParent(slot.transform, false);
        m_LaserDuration =GameObject.Instantiate( Resources.Load<AudioSource>("Perfabs/Audio/LaserDuration")).GetComponent<AudioSource>();
        if(m_LaserDuration)
        {
            m_LaserDuration.transform.SetParent(m_Laser.transform);
            m_LaserDuration.loop=true;
        }

        var endObj = GameObject.Instantiate(Resources.Load<GameObject>(m_BoomEndEffect));
        if (endObj)
        {
            m_LaserBoomEndObj = endObj.GetComponent<ParticleSystem>();
            m_LaserBoomEndObj.transform.SetParent(m_Laser.transform);
            m_LaserBoomEndObj.transform.localScale = new Vector3(1,1,1);
            m_LaserBoomEndObj.transform.localPosition = new Vector3(0, 0, 0);
        }
    }
    public override FlyItem Fire(GameObject ship, WeaponSlot slot, Vector3 position, Vector3 direction)
    {
        var fireShip = ship.GetComponent<Ship>();
        if (fireShip.m_ShipStruct.Electric < m_EnergyConsumption)
            return null;
        fireShip.m_ShipStruct.Electric -= m_EnergyConsumption;

        m_Laser.gameObject.transform.SetParent(slot.EmiterObject.transform, false);
        m_Laser.transform.localScale = new Vector3(1 / slot.transform.lossyScale.x, 1 / slot.transform.lossyScale.y, 1 / slot.transform.lossyScale.z);
        m_LaserDuration.gameObject.transform.SetParent(slot.EmiterObject.transform);
        m_LaserDuration.gameObject.transform.localPosition = new Vector3(0,0,0);
        float range = ShutRange;
        var layerMask = LayerMask.GetMask("Ship") | LayerMask.GetMask("Shild") | LayerMask.GetMask("Missile");
        var hits = Physics2D.RaycastAll(slot.transform.position, direction, range, layerMask);
        bool isHit = false;

        if (IsDamage)
            m_ShotErrorValue = 1;
        foreach (var hit in hits)
        {
            if (hit && (UtilsGame.IsOfShips(fireShip, hit.collider.gameObject) || hit.collider.gameObject.GetComponent<MissileFunction>() != null))
            {
                isHit = true;
                range = (new Vector3(hit.point.x, hit.point.y, 0) - m_Laser.transform.position).magnitude;
                if(IsDamage)
                {
                    FlyItem.CalcDamage(hit.collider, ship, Damage, m_DamageType);
                }
                if (m_LaserBoomEndObj)
                {
                    m_LaserBoomEndObj.transform.position = hit.point;
                    if(!m_LaserBoomEndObj.isPlaying)
                        m_LaserBoomEndObj.Play();
                }
                break;
            }
        }
        if(!isHit && m_LaserBoomEndObj && m_LaserBoomEndObj.isPlaying)
        {
            m_LaserBoomEndObj.Stop();
        }
        m_Laser.SetPosition(0, new Vector3(0, m_IsBilibili *m_Width, 0));
        m_Laser.SetPosition(1, new Vector3(0, 1, 0) * range);

        if(m_IsBilibili == 0)
        {
            PlayFireSound(fireShip, position);
            m_LaserDuration.loop = true;
            m_LaserDuration.Play();
        }
        m_IsBilibili = Mathf.Clamp(m_IsBilibili + Time.deltaTime*10f, 0, 1);

        m_AttenuationCount = 0;
        m_Laser.gameObject.SetActive(true);
        return null;
    }

    public override void FireOnlyEffect(GameObject ship, WeaponSlot slot, Vector3 position, Vector3 direction)
    {
        if(ship)
            m_Ship = ship.GetComponent<Ship>();
        if(slot != null)
            Slot = slot;
        IsDamage = false;
        Fire(ship, slot, position, direction);
    }
    public override int update()
    {
        if (UtilsGame.IsOnline() && m_Ship && !UtilsGame.IsServer(m_Ship.gameObject) && !m_Ship.isLocalPlayer)
        {
            if(m_ShotErrorValue > 0 && Slot)
                    Slot.FireOnlyEffect();
        }
        base.update();
        if (m_IsBilibili <= 0)
        {
            if(m_LaserDuration.loop)
                m_LaserDuration.loop = false;
            return 1;
        }
        m_AttenuationCount += Time.deltaTime;
        if (m_AttenuationCount >= m_Attenuation)
        {
            m_IsBilibili = Mathf.Clamp(m_IsBilibili - Time.deltaTime * 2, 0, 1);
        }

        if (m_IsBilibili <= 0)
        {
            m_Laser.gameObject.SetActive(false);
            
        }
        float bilibili = Mathf.Clamp(m_IsBilibili, 0, 1);
        m_StartColor.w = Mathf.Clamp(bilibili * 10, 0, 1);
        m_EndColor.w = Mathf.Clamp(bilibili, 0.5f, 1);
        m_Laser.startColor = m_StartColor;
        m_Laser.endColor = m_EndColor;
        m_Laser.startWidth = m_Width * 1.3f * bilibili;
        m_Laser.endWidth = m_Width *0.8f* bilibili;
        return 1;
    }

}